package Netty.NIO;

import io.netty.channel.ServerChannel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * 使用多路复用器
 *
 * @author hecai
 * @date 2021/11/9
 */
public class SelectorNioServer {

    public static void main(String[] args) throws IOException {
        // 创建NIO
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 绑定端口号
        serverSocketChannel.bind(new InetSocketAddress(9090));
        // 设置非阻塞
        serverSocketChannel.configureBlocking(false);
        // 打开Selector处理Channel 即创建epoll
        Selector selector = Selector.open();
        // 把serverSocketChannel注册到selector上
        // 并且将accept连接操作进行关联
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务启动成功");

        while (true) {
            // 阻塞等待需要处理的事件发生
            // 如果条件成立，说明本次询问selector，并没有获取到任何准备好的、感兴趣的事件
            // java程序对多路复用IO的支持也包括阻塞模式和非阻塞模式
            int select = selector.select();
            if (select == 0) {
                continue;
            }
            // 获取selector中注册的全部事件 SelectionKey 实例
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            //遍历 SelectionKey 对事件进行处理
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                
                if (selectionKey.isAcceptable()) {
//                    ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
//                    SocketChannel socketChannel = server.accept();
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("客户端连接成功");
                } else if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int read = socketChannel.read(readBuffer);
                    if (read > 0) {
                        // 处理进来的数据
                        System.out.println("收到数据: " + new String(readBuffer.array()).trim());
                        readBuffer.clear();
                        ByteBuffer buffer = ByteBuffer.wrap("返回给客户端的数据....".getBytes());
                        socketChannel.write(buffer);
                    } else if (read == -1) {
                        socketChannel.close();
                    }
                }
            }


        }


    }
}
